﻿
// <copyright file="ControllableComponentsUserControl.cs" company="Subhadra Software Solutions">
//   
// </copyright>
// <summary>
//   The controllable components user control.
// </summary>

namespace SubhadraSolutions.Sharp.Utils.ServiceProcess
{
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Windows.Forms;

    using BrightIdeasSoftware;

    using SubhadraSolutions.Sharp.Utils.Contracts;

    /// <summary>
    /// The controllable components user control.
    /// </summary>
    public partial class ControllableComponentsUserControl : UserControl
    {
        #region Fields

        /// <summary>
        /// The controllables.
        /// </summary>
        private List<IControllable> _controllables;

        #endregion Fields

        #region Constructors and Finalizers

        /// <summary>
        /// Initializes a new instance of the <see cref="ControllableComponentsUserControl"/> class.
        /// </summary>
        public ControllableComponentsUserControl()
        {
            this.InitializeComponent();

            this.setDelegates();
            this.treeListView1.VirtualMode = true;
            this.toolStrip1.ImageList = this.imageList1;
            TreeListView.TreeRenderer renderer = this.treeListView1.TreeColumnRenderer;
            renderer.LinePen = new Pen(Color.Firebrick, 0.5f) { DashStyle = DashStyle.Dot };
            this.enableDisableButtons(null);
        }

        #endregion Constructors and Finalizers

        // private void autosizeColumns()
        // {
        // this.SuspendLayout();
        // foreach (ColumnHeader col in treeListView1.Columns)
        // {
        // //auto resize column width

        // int colWidthBeforeAutoResize = col.Width;
        // col.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize);
        // int colWidthAfterAutoResizeByHeader = col.Width;
        // col.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
        // int colWidthAfterAutoResizeByContent = col.Width;

        // if (colWidthAfterAutoResizeByHeader > colWidthAfterAutoResizeByContent)
        // col.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize);

        // //specific adjusts

        // //first column
        // if (col.Index == 0)
        // //we have to manually take care of tree structure, checkbox and image
        // col.Width += 16 + 16 + treeListView1.SmallImageSize.Width;
        // //last column
        // else if (col.Index == treeListView1.Columns.Count - 1)
        // //avoid "fill free space" bug
        // if (colWidthBeforeAutoResize > colWidthAfterAutoResizeByContent)
        // col.Width = colWidthBeforeAutoResize;
        // else
        // col.Width = colWidthAfterAutoResizeByContent;
        // }
        // this.ResumeLayout();
        // }
        #region Public Properties

        /// <summary>
        /// Gets or sets the refresh interval in milliseconds.
        /// </summary>
        public int RefreshIntervalInMilliseconds
        {
            get
            {
                return this.timer1.Interval;
            }

            set
            {
                if (value > 0)
                {
                    this.timer1.Interval = value;
                }
            }
        }

        #endregion Public Properties

        #region Public Methods and Operators

        /// <summary>
        /// The bind.
        /// </summary>
        /// <param name="controllables">
        /// The controllables.
        /// </param>
        public void Bind(IEnumerable<IControllable> controllables)
        {
            if (this.components != null)
            {
                this._controllables = new List<IControllable>();
                this._controllables.AddRange(controllables);

                this.treeListView1.Roots = this._controllables;
                this.treeListView1.ExpandAll();
                this.timer1.Enabled = true;
            }
            else
            {
                this.treeListView1.Roots = null;
                this._controllables = null;
                this.timer1.Enabled = false;
            }
        }

        #endregion Public Methods and Operators

        #region Methods

        /// <summary>
        /// The enable disable buttons.
        /// </summary>
        /// <param name="controllable">
        /// The controllable.
        /// </param>
        private void enableDisableButtons(IControllable controllable)
        {
            this.startToolStripButton.Enabled = this.stopToolStripButton.Enabled = this.pauseToolStripButton.Enabled = this.resumeToolStripButton.Enabled = false;
            if (controllable != null)
            {
                switch (controllable.Controller.State)
                {
                    case ControllableComponentState.NotStarted:
                    case ControllableComponentState.Stopped:
                        this.startToolStripButton.Enabled = true;
                        break;

                    case ControllableComponentState.Busy:
                    case ControllableComponentState.Idle:
                        this.stopToolStripButton.Enabled = true;
                        if (controllable.Controller.SupportsPauseAndResume)
                        {
                            this.pauseToolStripButton.Enabled = true;
                        }

                        break;

                    case ControllableComponentState.Paused:
                        this.resumeToolStripButton.Enabled = true;
                        break;
                }
            }
        }

        /// <summary>
        /// The perform controllable action.
        /// </summary>
        /// <param name="action">
        /// The action.
        /// </param>
        /// <param name="controllable">
        /// The controllable.
        /// </param>
        private void performControllableAction(ComponentControllerAction action, IControllable controllable)
        {
            switch (action)
            {
                case ComponentControllerAction.Start:
                    controllable.Controller.Start();
                    break;

                case ComponentControllerAction.Stop:
                    controllable.Controller.Stop();
                    break;

                case ComponentControllerAction.Pause:
                    controllable.Controller.Pause();
                    break;

                case ComponentControllerAction.Resume:
                    controllable.Controller.Resume();
                    break;
            }
        }

        /// <summary>
        /// The set delegates.
        /// </summary>
        private void setDelegates()
        {
            this.treeListView1.CanExpandGetter = x => x is ICompositeControllable;
            this.treeListView1.ChildrenGetter = delegate(object x)
                {
                    var composite = x as ICompositeControllable;
                    return composite.Controllables;
                };

            this.busyIdleShareOlvColumn.AspectGetter = delegate(object x)
                {
                    var controller = ((IControllable)x).Controller as IMetricsEnabledComponentController;

                    if (controller == null)
                    {
                        return 0;
                    }

                    return controller.BusyPercentage;
                };
            this.stateOlvColumn.AspectGetter = delegate(object x)
                {
                    IComponentController controller = ((IControllable)x).Controller;

                    if (controller == null)
                    {
                        return null;
                    }

                    return controller.State.ToString();
                };
            this.supportsPauseAndResumeOlvColumn.AspectGetter = delegate(object x)
                {
                    IComponentController controller = ((IControllable)x).Controller;

                    if (controller == null)
                    {
                        return null;
                    }

                    return controller.SupportsPauseAndResume;
                };
            this.numberOfThreadsBeingServedOlvColumn.AspectGetter = delegate(object x)
                {
                    var controller = ((IControllable)x).Controller as IMetricsEnabledComponentController;

                    if (controller == null)
                    {
                        return null;
                    }

                    return controller.NumberOfThreadsBeingServed;
                };
            this.idlePercentageOlvColumn.AspectGetter = delegate(object x)
                {
                    var controller = ((IControllable)x).Controller as IMetricsEnabledComponentController;

                    if (controller == null)
                    {
                        return null;
                    }

                    return Math.Round(controller.IdlePercentage, 2) + "%";
                };
            this.busyPercentageOlvColumn.AspectGetter = delegate(object x)
                {
                    var controller = ((IControllable)x).Controller as IMetricsEnabledComponentController;

                    if (controller == null)
                    {
                        return null;
                    }

                    return Math.Round(controller.BusyPercentage, 2) + "%";
                };
            this.timeSpentInIdleOlvColumn.AspectGetter = delegate(object x)
                {
                    var controller = ((IControllable)x).Controller as IMetricsEnabledComponentController;

                    if (controller == null)
                    {
                        return null;
                    }

                    return StringHelper.TimeSpanToString(controller.TimeSpentInIdle);
                };
            this.timeSpentInBusyOlvColumn.AspectGetter = delegate(object x)
                {
                    var controller = ((IControllable)x).Controller as IMetricsEnabledComponentController;

                    if (controller == null)
                    {
                        return null;
                    }

                    return StringHelper.TimeSpanToString(controller.TimeSpentInBusy);
                };

            this.timeSpentInStoppedOlvColumn.AspectGetter = delegate(object x)
                {
                    var controller = ((IControllable)x).Controller as IMetricsEnabledComponentController;

                    if (controller == null)
                    {
                        return null;
                    }

                    return StringHelper.TimeSpanToString(controller.TimeSpentInStopped);
                };
            this.timeSpentInPausedOlvColumn.AspectGetter = delegate(object x)
                {
                    var controller = ((IControllable)x).Controller as IMetricsEnabledComponentController;

                    if (controller == null)
                    {
                        return null;
                    }

                    return StringHelper.TimeSpanToString(controller.TimeSpentInPaused);

                    // return controller.TimeSpentInPaused;
                };
        }

        /// <summary>
        /// The timer 1_ tick.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void timer1_Tick(object sender, EventArgs e)
        {
            if (this._controllables != null)
            {
                this.treeListView1.RefreshObjects(this._controllables);
            }
        }

        /// <summary>
        /// The tool strip button_ click.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void toolStripButton_Click(object sender, EventArgs e)
        {
            var controllable = this.treeListView1.SelectedObject as IControllable;
            if (controllable != null)
            {
                ComponentControllerAction action;
                if (sender == this.startToolStripButton)
                {
                    action = ComponentControllerAction.Start;
                }
                else
                {
                    if (sender == this.stopToolStripButton)
                    {
                        action = ComponentControllerAction.Stop;
                    }
                    else
                    {
                        action = sender == this.pauseToolStripButton ? ComponentControllerAction.Pause : ComponentControllerAction.Resume;
                    }
                }

                this.performControllableAction(action, controllable);
                this.enableDisableButtons(controllable);
            }
        }

        /// <summary>
        /// The tree list view 1_ selected index changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void treeListView1_SelectedIndexChanged(object sender, EventArgs e)
        {
            var listView = (ObjectListView)sender;
            var controllable = listView.SelectedObject as IControllable;
            this.enableDisableButtons(controllable);
        }

        #endregion Methods
    }
}